import logging
import os
import random
import threading
from datetime import datetime
from operator import and_

from flask import request, jsonify, send_file
from sqlalchemy import desc

from app.base import base
from .amazonServiceFilterTxt import intenalFilterAmazonNumbers
from .numberTask import updateTaskStatus
from .. import db
from ..models.NumberTask import NumberTask

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


def load_number_ranges_from_file(txtName):
    filename = f"areacode_{txtName}.txt"
    number_ranges = []
    try:
        with open(filename, "r") as file:
            for line in file:
                parts = line.strip().split('-')
                if len(parts) == 4:
                    number_ranges.append({
                        'country_code': parts[0],
                        'domestic_code': parts[1],
                        'start_range': int(parts[2]),
                        'end_range': int(parts[3])
                    })
    except Exception as e:
        logger.info(f"手机号码生成|读取区域文件异常{e}")
    return number_ranges


def generate_and_save_numbers_txt(number_ranges, count, number_g_path):
    generated_count = 0  # Current count of generated numbers

    try:
        with open(number_g_path, "w") as file:
            full_path = os.path.abspath(number_g_path)
            logger.info(f"手机号码生成|文件创建路径{full_path}")
            while generated_count < int(count):
                for number_range in number_ranges:
                    if generated_count >= int(count):
                        break  # Exit if the desired count is reached

                    country_code = str(number_range['country_code'])
                    domestic_code = str(number_range['domestic_code'])
                    start = number_range['start_range']  # Ensure minimum value is 1000001
                    end = number_range['end_range']

                    # Randomly generate a number
                    random_number = random.randint(start, end)
                    full_number = f"{country_code}{domestic_code}{random_number}"

                    # Write only the full number to the output file
                    file.write(f"{full_number}\n")
                    generated_count += 1  # Increment the count of generated numbers

                    # Exit if the desired count is reached
                    if generated_count >= int(count):
                        break

    except Exception as e:
        logger.info(f"手机号码生成|生成过程异常{e}")


@base.route('/number/generateNumbersTxtByTxtName', methods=['GET'])
def generate_numbers_by_task_api():
    # 获取请求参数中的 task_id
    try:
        country = request.args.get('country')
        count = request.args.get('count')
        number_g_path = request.args.get('number_g_path')
        logger.info(f"手机号码生成|获取请求参数: {country}")
        if not country:
            return jsonify({"error": "参数 'task_id' 是必需的"}), 400
        # 随机生成号码并保存
        number_ranges = load_number_ranges_from_file(country)
        logger.info(f"手机号码生成|读取区域文件成功......")
        generate_and_save_numbers_txt(number_ranges, count, number_g_path)
        logger.info(f"手机号码生成|已成功生成并保存{count}条号码")
        return jsonify({"message": f"已成功生成并保存 {count} 条号码"}), 200
    except Exception as e:
        logger.info(f"手机号码生成|生成号码服务异常:{e}")


def internalGenerateNumbers(country, count, number_g_path):
    try:
        logger.info(f"内部-手机号码生成|获取请求参数:国家{country},数量{count},路径{number_g_path}")
        if not country:
            return jsonify({"error": "参数 'task_id' 是必需的"}), 400
        # 随机生成号码并保存
        number_ranges = load_number_ranges_from_file(country)
        logger.info(f"内部-手机号码生成|读取区域文件成功......")
        generate_and_save_numbers_txt(number_ranges, count, number_g_path)
        logger.info(f"内部-手机号码生成|已成功生成并保存{count}条号码")

    except Exception as e:
        logger.info(f"内部-手机号码生成|生成号码服务异常:{e}")


@base.route('/number/download', methods=['GET'])
def download_file():
    try:
        # 获取请求参数中的 txtName
        absolute_path = request.args.get('absolute_path')
        logger.info(f"手机号码生成|导出路径{absolute_path}")
        # 返回文件下载链接
        return send_file(absolute_path, as_attachment=True)
    except Exception as e:
        logger.error(f"手机号码生成|下载服务异常: {e}")
        return jsonify({"error": "下载服务异常"}), 500


# 允许的文件扩展名
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}


def allowed_file(filename):
    # 检查文件扩展名是否允许
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@base.route('/number/upload', methods=['POST'])
def upload_file():
    try:
        # 检查请求中是否包含文件
        if 'file' not in request.files:
            return jsonify({"error": "没有文件被上传"}), 400
        file = request.files['file']
        # 如果用户没有选择文件
        if file.filename == '':
            return jsonify({"error": "未选择文件"}), 400

        # 检查文件扩展名是否允许
        if file and allowed_file(file.filename):
            filename = file.filename
            file_path = os.path.join(os.getcwd(), filename)
            # 保存文件
            file.save(file_path)
            logger.info(f"手机号码生成|文件上传成功")
            return jsonify({"message": "文件上传成功", "file_path": file_path}), 200
        else:
            logger.info(f"手机号码生成|不允许的文件类型")
            return jsonify({"error": "不允许的文件类型"}), 400
    except Exception as e:
        logger.error(f"手机号码生成|上传服务异常: {e}")
        return jsonify({"error": "上传服务异常"}), 500


@base.route('/number/addOrUpdateTask', methods=['GET'])
def add_or_update_task():
    logger.info(f"手机号码生成|开始创建任务")
    try:
        # 获取请求数据
        # 获取请求参数
        task_id = request.args.get('id')  # 获取任务 ID
        task_name = request.args.get('taskName')
        execute_time = request.args.get('executeTime')
        country = request.args.get('country')
        status = request.args.get('status')
        task_type = request.args.get('type')
        step = request.args.get('step')
        total_num = request.args.get('totalNum')
        success_num = request.args.get('successNum')
        if task_id:
            # 查找并更新现有任务
            task = NumberTask.query.get(task_id)
            # 仅更新不为空的字段
            if task_name:
                task.task_name = task_name
            if execute_time:
                task.execute_time = execute_time
            if country:
                task.country = country
            if status is not None:
                task.status = status
            if task_type is not None:
                task.type = task_type
            if step is not None:
                task.step = step
            if total_num is not None:
                task.total_num = total_num
            if success_num is not None:
                task.success_num = success_num
            task.update_time = datetime.now()  # 更新时间
        else:
            # 创建新任务
            now = datetime.now()
            # 格式化输出：年月日-时分秒毫秒
            task_uuid = now.strftime("%Y%m%d-%H%M%S%f")
            number_g_path = os.path.join(os.getcwd(), f"{country}_g_{task_uuid}.txt")
            number_s_path = os.path.join(os.getcwd(), f"{country}_s_{task_uuid}.txt")
            task = NumberTask(
                task_name=task_name,
                execute_time=execute_time or datetime.now(),
                country=country,
                status=status,
                type=task_type,
                step=step,
                total_num=total_num,
                success_num=success_num,
                number_g_path=number_g_path,
                number_s_path=number_s_path,
                task_uuid=task_uuid,
                create_time=datetime.now(),
                update_time=datetime.now()
            )
            db.session.add(task)
        # 提交更改
        db.session.commit()
        logger.info(f"手机号码生成|任务创建完成")
        # 创建线程并启动异步任务
        threading.Thread(target=generateAndFilterNumbers,
                         args=(task.id, task.country, task.total_num, task.number_g_path, task.number_s_path,
                               task.step)).start()
        return jsonify({"message": "任务创建成功", "taskId": task.id}), 200
    except Exception as e:
        logger.error(f"手机号码生成|任务操作异常{e}")
        return jsonify({"message:任务操作失败"}), 500


# 定义生成和筛选的组合函数
def generateAndFilterNumbers(task_id, country, total_num, number_g_path, number_s_path, step):
    try:
        updateTaskStatus(task_id, 1)
        logger.info(f"内部-手机号码生成|任务手机号生成中<{task_id}>")
        # 执行生成号码的逻辑
        internalGenerateNumbers(country, total_num, number_g_path)
        updateTaskStatus(task_id, 2)
        logger.info(f"内部-手机号码生成|任务手机号生成完成<{task_id}>")
        # 如果 step 不为 0，执行筛选
        if step != 0:
            intenalFilterAmazonNumbers(number_g_path, number_s_path)
    except Exception as e:
        logging.error(f"手机号码生成|任务执行出错: {e}")


@base.route('/number/getTaskList', methods=['GET'])
def getTaskList():
    try:
        # 获取请求参数
        task_name = request.args.get('taskName', default='', type=str)
        country = request.args.get('country', default='', type=str)
        start_time = request.args.get('startTime', type=str)  # 开始时间
        end_time = request.args.get('endTime', type=str)  # 结束时间
        page = request.args.get('page', default=1, type=int)  # 当前页
        per_page = request.args.get('perPage', default=10, type=int)  # 每页数量
        logger.info(
            f"手机号码生成|任务查询参数 taskName={task_name}, country={country}, startTime={start_time}, endTime={end_time}, page={page}, perPage={per_page}")
        # 查询任务
        query = NumberTask.query
        # 根据 taskName 进行过滤
        if task_name:
            query = query.filter(NumberTask.task_name.like(f'%{task_name}%'))
        # 根据 country 进行过滤
        if country:
            query = query.filter(NumberTask.country == country)
        # 根据创建时间范围进行过滤
        if start_time and end_time:
            try:
                start_datetime = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
                end_datetime = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
                query = query.filter(
                    and_(NumberTask.create_time >= start_datetime, NumberTask.create_time <= end_datetime))
            except ValueError:
                return jsonify({"error": "时间格式不正确，应为 'YYYY-MM-DD HH:MM:SS'"}), 400
        # 按 ID 倒序排列
        query = query.order_by(desc(NumberTask.id))
        # 分页
        paginated_tasks = query.paginate(page=page, per_page=per_page, error_out=False)
        # 转化为 JSON 格式
        task_list = [task.to_json() for task in paginated_tasks.items]
        # 返回分页结果
        return jsonify({
            "taskList": task_list,
            "total": paginated_tasks.total,
            "page": paginated_tasks.page,
            "perPage": paginated_tasks.per_page,
            "pages": paginated_tasks.pages
        }), 200
    except Exception as e:
        logger.error(f"手机号码生成|获取任务列表失败: {e}")
        return jsonify({"error": f"获取任务列表失败: {e}"}), 500


@base.route('/number/getCountryNameList', methods=['GET'])
def getCountryNameList():
    logger.info(f"手机号码生成|获取可以筛选的国家列表")
    root_dir = os.getcwd()  # 获取项目根目录
    try:
        # 列出根目录下以 "areacode_" 开头的文件
        files = [
            f.replace("areacode_", "").replace(".txt", "")
            for f in os.listdir(root_dir)
            if os.path.isfile(os.path.join(root_dir, f)) and f.startswith("areacode_")
        ]
        return jsonify({"countryList": files}), 200
    except Exception as e:
        return jsonify({"error": f"获取文件列表失败: {e}"}), 500


@base.route('/number/countFileLine', methods=['GET'])
def countFileLine():
    try:
        # 从请求中获取参数
        task_id = request.args.get('task_id')
        number_s_path = request.args.get('file_path')
        # 参数验证
        if not task_id or not number_s_path:
            return jsonify({"error": "参数缺失"}), 200
        # 检查文件路径是否存在
        if not os.path.isfile(number_s_path):
            logger.warning(f"countFileLine|文件不存在：{number_s_path}")
            return jsonify({"error": "文件不存在"}), 200
            # return jsonify({"task_id": task_id, "count": 0}), 200
        # 初始化行数
        line_count = 0
        # 读取文件并计算行数
        with open(number_s_path, 'r', encoding='utf-8') as file:
            for line_count, _ in enumerate(file, 1):
                pass
        # 记录日志并返回条数
        logger.info(f"内部-亚马逊数据筛查|任务修改筛选数量<{task_id}> 总条数:{line_count}")
        return jsonify({"task_id": task_id, "count": line_count}), 200
    except IOError as e:
        logger.error(f"countFileLine|读取文件错误: {e}")
        return jsonify({"error": "读取文件错误"}), 200
    except Exception as e:
        logger.error(f"countFileLine|出现错误: {e}")
        return jsonify({"error": "接口服务异常"}), 200
